grammar yy;

@header {
/*
 *  Copyright 2011 Iurii Dunko, Iana Potochniak.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *  under the License.
 */

package org.opu.yyminijava;

import org.opu.yyminijava.syntaxtree.*;
import org.opu.yyminijava.syntaxtree.primary.*;
}

@lexer::header {
/*
 *  Copyright 2011 Iurii Dunko, Iana Potochniak.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *  under the License.
 */

package org.opu.yyminijava;
}

//
// =========================  Lexical structure  ==========================
//

// key words

ABSTRACT:    'abstract';

CONTINUE:    'continue';

FOR:         'for';

NEW:         'new';

SWITCH:      'switch';

DEFAULT:    'default';

BOOLEAN:    'boolean';

DO:         'do';

IF:         'if';

PRIVATE:    'private';

THIS:       'this';

BREAK:      'break';

DOUBLE:     'double';

PROTECTED:  'protected';

BYTE:       'byte';

ELSE:       'else';

PUBLIC:     'public';

CASE:       'case';

RETURN:     'return';

INT:        'int';

SHORT:      'short';

CHAR:       'char';

FINAL:      'final';

STATIC:     'static';

VOID:       'void';

CLASS:      'class';

LONG:       'long';

FLOAT:      'float';

NATIVE:     'native';

SUPER:      'super';

WHILE:      'while';

TRUE:       'true';

FALSE:      'false';

NULL:       'null';

EXTENDS:    'extends';

THROWS:     'throws';

// lexems
ID  :    ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*
    ;

COMMENT
    :   '//' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;}
    |   '/*' ( options {greedy=false;} : . )* '*/' {$channel=HIDDEN;}
    ;

WS  :   ( ' '
        | '\t'
        | '\r'
        | '\n'
        ) {$channel=HIDDEN;}
    ;

STRINGLITERAL
    :  '"' ( ESC_SEQ | ~('\\'|'"') )* '"'
    ;

CHARACTERLITERAL
    :  '\'' ( ESC_SEQ | ~('\''|'\\') ) '\''
    ;

fragment
HEX_DIGIT : ('0'..'9'|'a'..'f'|'A'..'F') ;

fragment
ESC_SEQ
    :   '\\' ('b'|'t'|'n'|'f'|'r'|'\"'|'\''|'\\')
    |   UNICODE_ESC
    |   OCTAL_ESC
    ;

fragment
OCTAL_ESC
    :   '\\' ('0'..'3') ('0'..'7') ('0'..'7')
    |   '\\' ('0'..'7') ('0'..'7')
    |   '\\' ('0'..'7')
    ;

fragment
UNICODE_ESC
    :   '\\' 'u' HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
    ;

INTEGERLITERAL
    : '0'
    | ('1'..'9') ('0'..'9')*
    ;

// Terminals

RECTANGLE_OPEN:     '[';
RECTANGLE_CLOSE:    ']';
DOT:                '.';
STATEMENT_END:      ';';
BLOCK_START:        '{';
BLOCK_END:          '}';
COMA:               ',';
GROUP_START:        '(';
GROUP_END:          ')';
EQUALLY:            '=';
QUESTION_MARK:      '?';
DOUBLE_POINT:       ':';

//
// =========================  Grammar  ==========================
//

// THE SYNTACTIC GRAMMAR

goal returns [Goal g]
@init {
    $g = new Goal();
}
    : compilationUnit {$g.setCompilationUnit($compilationUnit.cUnit);}
    ;

// LEXICAL STRUCTURE

integerLiteral returns [Literal iLiteral]
    : INTEGERLITERAL {
        $iLiteral = new IntegerLiteral(Integer.parseInt($INTEGERLITERAL.getText()));
    }
    ;

booleanLiteral returns [Literal bLiteral]
    : TRUE {$bLiteral = new BooleanLiteral(true);}
    | FALSE {$bLiteral = new BooleanLiteral(false);}
    ;

charLiteral returns [Literal chLiteral]
    : CHARACTERLITERAL {
        $chLiteral = new CharLiteral($CHARACTERLITERAL.getText().charAt(0));
    }
    ;

stringLiteral returns [Literal sLiteral]
    : STRINGLITERAL {$sLiteral = new StringLiteral($STRINGLITERAL.getText());}
    ;

nullLiteral returns [Literal nullLiteral]
    : NULL {$nullLiteral = new NullLiteral();}
    ;

literal returns [Literal literal]
    : integerLiteral {$literal = $integerLiteral.iLiteral;}
    | booleanLiteral {$literal = $booleanLiteral.bLiteral;}
    | charLiteral    {$literal = $charLiteral.chLiteral;}
    | stringLiteral  {$literal = $stringLiteral.sLiteral;}
    | nullLiteral    {$literal = $nullLiteral.nullLiteral;}
    ;

// TYPES

type returns [Type type]
    : primitiveType {$type = $primitiveType.pType;}
    | referenceType {$type = $referenceType.rType;}
    ;

primitiveType returns [PrimitiveType pType]
    : INT       {$pType = new PrimitiveType(PrimitiveType.Type.INT);}
    | BOOLEAN   {$pType = new PrimitiveType(PrimitiveType.Type.BOOLEAN);}
    ;

referenceType returns [ReferenceType rType]
    : classType {$rType = $classType.cType;}
    | arrayType {$rType = $arrayType.arType;}
    ;

classType returns [ClassType cType]
    : name {$cType = new ClassType($name.name);}
    ;

arrayType returns [ArrayType arType]
@init{
    $arType = new ArrayType();
}
@after {
    arType.initialisationComplete();
}
    : (
        primitiveType {$arType.setType($primitiveType.pType);}
      | classType {$arType.setType($classType.cType);}
      ) RECTANGLE_OPEN RECTANGLE_CLOSE {$arType.setDimension(1);}
    ;

// NAMES

name returns [Name name]
@init{
    $name = new Name();
}
    : id=ID {$name.addName($id.getText());}
    (DOT id=ID{$name.addName($id.getText());})*
    ;

// PACKAGES

compilationUnit returns[CompilationUnit cUnit]
@init{
    $cUnit = new CompilationUnit();
}
    : (typeDeclaration {$cUnit.addType($typeDeclaration.typeDeclaration);})*
    ;

typeDeclaration returns[TypeDeclaration typeDeclaration]
@init{
    $typeDeclaration = new TypeDeclaration();
}
    : classDeclaration {
        $typeDeclaration.setClassDeclaration($classDeclaration.cd);
    }
    ;

// MODIFIERS

modifiers returns [Modifiers modifiers]
@init{
    $modifiers = new Modifiers();
}
    : (modifier {$modifiers.addModifierType($modifier.modifier);})*
    ;

modifier returns [Modifier modifier]
    : PUBLIC {$modifier = Modifier.PUBLIC;}
    | STATIC {$modifier = Modifier.STATIC;}
    | NATIVE {$modifier = Modifier.NATIVE;}
    | ABSTRACT {$modifier = Modifier.ABSTRACT;}
    | FINAL {$modifier = Modifier.FINAL;}
    ;

// CLASSES

// Class Declaration

classDeclaration returns [ClassDeclaration cd]
@init {
    $cd = new ClassDeclaration();
}
    : modifiers {$cd.setModifiers($modifiers.modifiers);}
    CLASS ID {$cd.setName($ID.getText());}
    (EXTENDS classType{$cd.setSuperName($classType.cType);})?
    classBody {$cd.setClassBody($classBody.classBody);}
    ;

classBody returns [ClassBody classBody]
@init {
    $classBody = new ClassBody();
}
    : BLOCK_START (classMemberDeclaration {
        $classBody.addClassMemberDeclaration($classMemberDeclaration.cmDeclaration);
      } )* BLOCK_END
    ;

classMemberDeclaration returns [ClassMemberDeclaration cmDeclaration]
    : fieldDeclaration  {$cmDeclaration = $fieldDeclaration.fDeclaration;}
    | methodDeclaration {$cmDeclaration = $methodDeclaration.mDeclaration;}
    ;

// Field Declarations

fieldDeclaration returns [FieldDeclaration fDeclaration]
@init{
    $fDeclaration = new FieldDeclaration();
}
    : modifiers {$fDeclaration.setModifiers($modifiers.modifiers);}
      type {$fDeclaration.setType($type.type);}
      identifierList {$fDeclaration.setIdentifierList($identifierList.identifierList);}
        STATEMENT_END
    ;

identifierList returns [IdentifierList identifierList]
@init{
    $identifierList = new IdentifierList();
}
    : id1=ID {$identifierList.addName($id1.getText());}
      (COMA id1=ID{$identifierList.addName($id1.getText());})*
    ;

// Method Declarations

methodDeclaration returns [MethodDeclaration mDeclaration]
@init{
    $mDeclaration = new MethodDeclaration();
}
    : methodHeader {$mDeclaration.setHeader($methodHeader.methodHeader);}
      methodBody {$mDeclaration.setBody($methodBody.methodBody);}
    ;

methodHeader returns[MethodHeader methodHeader]
@init{
    $methodHeader = new MethodHeader();
}
    : modifiers {$methodHeader.setModifiers($modifiers.modifiers);}
    (
         type {$methodHeader.setType($type.type);}
        | VOID
    )
      methodDeclarator {$methodHeader.setDeclarator($methodDeclarator.methodDeclarator);}
      (THROWS classType {$methodHeader.setThrowsClass($classType.cType);}) ?
    ;

methodDeclarator returns[MethodDeclarator methodDeclarator]
@init{
    $methodDeclarator = new MethodDeclarator();
}
    : ID {$methodDeclarator.setSimpleName($ID.getText());}
    GROUP_START (formalParameterList{
        $methodDeclarator.setParameterList($formalParameterList.fParamList);
    })? GROUP_END
    ;

formalParameterList returns[FormalParameterList fParamList]
@init{
    $fParamList = new FormalParameterList();
}
    : fp=formalParameter {$fParamList.addParameter($fp.fParameter);}
      (COMA fp12=formalParameter {$fParamList.addParameter($fp12.fParameter);}) *
    ;

formalParameter returns[FormalParameter fParameter]
@init{
    $fParameter = new FormalParameter();
}
    : (type ID) {$fParameter = new FormalParameter($type.type, $ID.getText());}
    ;


methodBody returns[MethodBody methodBody]
@init{
    $methodBody = new MethodBody();
}
    : block {$methodBody.setBlock($block.block);}
    ;

// BLOCKS AND STATEMENTS

block returns [Block block]
@init {
    $block = new Block();
}
    : BLOCK_START (statement {
        $block.addStatement($statement.statement);
      })* BLOCK_END
    ;

localVariableDeclarationStatement returns [LocalVariableDeclarationStatement lDeclStmt]
@init{
    $lDeclStmt = new LocalVariableDeclarationStatement();
}
    : localVariableDeclaration {
        $lDeclStmt.setDeclaration($localVariableDeclaration.lDecl);
    } STATEMENT_END
    ;

localVariableDeclaration returns [LocalVariableDeclaration lDecl]
@init{
    $lDecl = new LocalVariableDeclaration();
}
    : type {$lDecl.setType($type.type);}
      variableDeclarators {$lDecl.setVariableDeclarators($variableDeclarators.vDeclrs);}
    ;

variableDeclarators returns [VariableDeclarators vDeclrs]
@init{
    $vDeclrs = new VariableDeclarators();
}
    : vd1=variableDeclarator {$vDeclrs.addVariable($vd1.vDecl);}
      (COMA vd1=variableDeclarator {$vDeclrs.addVariable($vd1.vDecl);})*
    ;

variableDeclarator returns [VariableDeclarator vDecl]
@init{
    $vDecl = new VariableDeclarator();
}
    : ID {$vDecl.setSimpleName($ID.getText());}
      ( EQUALLY expression {$vDecl.setExpression($expression.exp);} ) ?
    ;

statement returns [Statement statement]
    : localVariableDeclarationStatement {$statement = $localVariableDeclarationStatement.lDeclStmt;}
    | block {$statement = $block.block;}
    | methodCallStatement {$statement = $methodCallStatement.mCallStmt;}
    | ifElseStatement {$statement = $ifElseStatement.ifElsStmt;}
    | whileStatement {$statement = $whileStatement.whileStmt;}
    | doWhileStatement {$statement = $doWhileStatement.doWhileStmt;}
    | returnStatement {$statement = $returnStatement.retStmt;}
    | breakStatement {$statement = $breakStatement.brkStmt;}
    | continueStatement {$statement = $continueStatement.contStmt;}
    | forStatement {$statement = $forStatement.forStmt;}
    | STATEMENT_END {$statement = new StatementEmpty();}
    ;

methodCallStatement returns[MethodCallStatement mCallStmt]
@init{
    $mCallStmt = new MethodCallStatement();
}
@after{
    $mCallStmt.validate();
}
    : postfixExpression {$mCallStmt.setPostfixExpression($postfixExpression.pstfExp);}
      (EQUALLY expression {$mCallStmt.setExpression($expression.exp);})?
      STATEMENT_END
    ;

ifStatementPart returns[IfStatementPart ifStmtPrt]
@init{
    $ifStmtPrt = new IfStatementPart();
}
    : IF GROUP_START expression {$ifStmtPrt.setExpression($expression.exp);}
      GROUP_END
    ;

elseStatementPart returns[ElseStatementPart elsStmtPrt]
@init{
    $elsStmtPrt = new ElseStatementPart();
}
    : ELSE statement {$elsStmtPrt.setStatement($statement.statement);}
    ;

ifElseStatement returns[IfElseStatement ifElsStmt]
@init{
    $ifElsStmt = new IfElseStatement();
}
	: ifStatementPart {$ifElsStmt.setIfStatementPart($ifStatementPart.ifStmtPrt);}
      statement {$ifElsStmt.setStatement($statement.statement);}
      (elseStatementPart {$ifElsStmt.setElseStatementPart($elseStatementPart.elsStmtPrt);}) ?
	;

whileStatement returns[WhileStatement whileStmt]
@init{
    $whileStmt = new WhileStatement();
}
    : WHILE GROUP_START expression {$whileStmt.setExpression($expression.exp);}
      GROUP_END statement {$whileStmt.setStatement($statement.statement);}
    ;

doWhileStatement returns[DoWhileStatement doWhileStmt]
@init{
    $doWhileStmt = new DoWhileStatement();
}
    : DO statement {$doWhileStmt.setStatement($statement.statement);}
      WHILE GROUP_START expression {$doWhileStmt.setExpression($expression.exp);}
      GROUP_END STATEMENT_END
    ;

returnStatement returns[ReturnStatement retStmt]
@init{
    $retStmt = new ReturnStatement();
}
    : RETURN (expression {$retStmt.setExpression($expression.exp);}) ?
      STATEMENT_END
    ;

breakStatement returns[BreakStatement brkStmt]
@init{
    $brkStmt = new BreakStatement();
}
    : BREAK STATEMENT_END
    ;

continueStatement returns[ContinueStatement contStmt]
@init{
    $contStmt = new ContinueStatement();
}
    : CONTINUE STATEMENT_END
    ;

forStatement returns[ForStatement forStmt]
@init{
    $forStmt = new ForStatement();
}
    : FOR GROUP_START (forInit {$forStmt.setForInit($forInit.forInit);}) ?
      STATEMENT_END (expression {$forStmt.setForException($expression.exp);}) ?
      STATEMENT_END (forUpdate {$forStmt.setForUpdate($forUpdate.forUpdate);}) ?
      GROUP_END (statement {$forStmt.setStatement($statement.statement);})
    ;

forInit returns[ForInit forInit]
@init{
    $forInit = new ForInit();
}
    : statementExpressionList {
        $forInit.setExpressionPart($statementExpressionList.stExpLst);
    }
    | localVariableDeclaration 
        {$forInit.setExpressionPart($localVariableDeclaration.lDecl);
    }
    ;

forUpdate returns[ForUpdate forUpdate]
@init{
    $forUpdate = new ForUpdate();
}
    : statementExpressionList {
        $forUpdate.setExpressionList($statementExpressionList.stExpLst);
    }
    ;

statementExpressionList returns[StatementExpressionList stExpLst]
@init{
    $stExpLst = new StatementExpressionList();
}
    : stEx1=statementExpression {$stExpLst.addStatementExpression($stEx1.stExp);}
      (COMA stEx12=statementExpression {$stExpLst.addStatementExpression($stEx12.stExp);})*
    ;

statementExpression returns[StatementExpression stExp]
@init{
    $stExp = new StatementExpression();
}
    : ID {$stExp.setName($ID.getText());}
    EQUALLY expression {$stExp.setExpression($expression.exp);}
    ;

// EXPRESSIONS

arithmeticalMullOp returns[ArithmeticalMullOp arMullOp]
    : '*' {$arMullOp = ArithmeticalMullOp.MULTIPLICATION;}
    | '/' {$arMullOp = ArithmeticalMullOp.DIVISION;}
    ;

arithmeticalAddOp returns[ArithmeticalAddOp arAddOp]
    : '-' {$arAddOp = ArithmeticalAddOp.MINUS;}
    | '+' {$arAddOp = ArithmeticalAddOp.PLUS;}
    ;

compareOp returns[CompareOp compareOp]
    : '<' {$compareOp = CompareOp.LESS;}
    | '>' {$compareOp = CompareOp.BIGGER;}
    | '<=' {$compareOp = CompareOp.LESS_OR_EQUALS;}
    | '>=' {$compareOp = CompareOp.BIGGER_OR_EQUALS;}
    ;

logicalOp returns[LogicalOp logicalOp]
    : '==' {$logicalOp = LogicalOp.EQUAL;}
    | '!=' {$logicalOp = LogicalOp.NOT_EQUAL;}
    ;

booleanOp returns[BooleanOp booleanOp]
    : '||' {$booleanOp = BooleanOp.XOR;}
    | '&&' {$booleanOp = BooleanOp.XAND;}
    ;

prefixOp returns[PrefixOp prefixOp]
    : '-' {$prefixOp = PrefixOp.NEGATION;}
    | '!' {$prefixOp = PrefixOp.DENIAL;}
    ;

expression returns [Expression exp]
@init{
    $exp = new Expression();
}
    : booleanExpression {$exp.setBoolExp($booleanExpression.boolExp);}
    ;

booleanExpression returns[BooleanExpression boolExp]
@init{
    $boolExp = new BooleanExpression();
}
    : le1=logicalExpression {$boolExp.setLogExp($le1.logicExp);}
    (
        (booleanOp le12=logicalExpression) {
            $boolExp.add($booleanOp.booleanOp, $le12.logicExp);
        }
    )*
    ;

logicalExpression returns[LogicalExpression logicExp]
@init{
    $logicExp = new LogicalExpression();
}
    : ce1=compareExpression {$logicExp.setCmprExp($ce1.cmprExp);}
    (
        (logicalOp ce12=compareExpression) {
            $logicExp.add($logicalOp.logicalOp, $ce12.cmprExp);
        }
    )*
    ;

compareExpression returns[CompareExpression cmprExp]
@init{
    $cmprExp = new CompareExpression();
}
    : aae1=arithmeticalAddExpression {$cmprExp.setArAddExp($aae1.arAddExp);}
    (
        (compareOp aae12=arithmeticalAddExpression) {
            $cmprExp.add($compareOp.compareOp, $aae12.arAddExp);
        }
    )*
    ;

arithmeticalAddExpression returns[ArithmeticalAddExpression arAddExp]
@init{
    $arAddExp = new ArithmeticalAddExpression();
}
    : ame1=arithmeticalMullExpression {$arAddExp.setArMullExp($ame1.arMullExp);}
    (
        (arithmeticalAddOp ame12=arithmeticalMullExpression) {
            $arAddExp.add($arithmeticalAddOp.arAddOp, $ame12.arMullExp);
        }
    )*
    ;

arithmeticalMullExpression returns[ArithmeticalMullExpression arMullExp]
@init{
    $arMullExp = new ArithmeticalMullExpression();
}
    : pe1=prefixExpression {$arMullExp.setPrefxExp($pe1.prefxExp);}
    (
        (arithmeticalMullOp pe12=prefixExpression) {
            $arMullExp.add($arithmeticalMullOp.arMullOp, $pe12.prefxExp);
        }
    )*
    ;

prefixExpression returns[PrefixExpression prefxExp]
@init{
    $prefxExp = new PrefixExpression();
}
    : (prefixOp {$prefxExp.setPrefixOp($prefixOp.prefixOp);})?
    postfixExpression {$prefxExp.setPostfixExpression($postfixExpression.pstfExp);}
    ;

postfixExpression returns[PostfixExpression pstfExp]
@init{
    $pstfExp = new PostfixExpression();
}
@after{
    $pstfExp.validate();
}
    : primary {$pstfExp.setPrimary($primary.primary);}
    (suffix {$pstfExp.addSuffix($suffix.suffix);})*
    ;

suffix returns[Suffix suffix]
    : arrayAccess      {$suffix = $arrayAccess.arrAcs;}
    | methodInvocation {$suffix = $methodInvocation.mInvoc;}
    | fieldInvocation  {$suffix = $fieldInvocation.fInvoc;}
    ;

arrayAccess returns[ArrayAccess arrAcs]
@init{
    $arrAcs = new ArrayAccess();
}
    : RECTANGLE_OPEN expression {
        $arrAcs.setExpression($expression.exp);
    } RECTANGLE_CLOSE
    ;

methodInvocation returns[MethodInvocation mInvoc]
@init{
    $mInvoc = new MethodInvocation();
}
    : DOT methodCall {$mInvoc.setMethodCall($methodCall.mCall);}
    ;

fieldInvocation returns[FieldInvocation fInvoc]
@init{
    $fInvoc = new FieldInvocation();
}
    : DOT ID {$fInvoc.setSimpleName($ID.getText());}
    ;

argumentList returns [ArgumentList argLst]
@init{
    $argLst = new ArgumentList();
}
    : exp2=expression {$argLst.addExpression($exp2.exp);}
    (COMA exp2=expression {$argLst.addExpression($exp2.exp);})*
    ;

primary returns[Primary primary]
    : GROUP_START expression {
        $primary = new PrimaryFromExpression($expression.exp);
     } GROUP_END
    | literal     {$primary = new PrimaryFromLiteral($literal.literal);}
    | THIS        {$primary = new PrimaryFromThis();}
    | methodCall  {$primary = new PrimaryMethodCall($methodCall.mCall);}
    | newInstance {$primary = new PrimaryFromNewInstance($newInstance.newInst);}
    | ID          {$primary = new PrimaryFromIdentifier($ID.getText());}
    ;

methodCall returns[MethodCall mCall]
@init{
    $mCall = new MethodCall();
}
    : ID {$mCall.setSimpleName($ID.getText());}
    GROUP_START (argumentList {$mCall.setArgumentList($argumentList.argLst);})?
    GROUP_END
    ;

classInstanceCreationExpression returns[ClassInstanceCreationExpression clsCreateExp]
@init{
    $clsCreateExp = new ClassInstanceCreationExpression();
}
    : classType {$clsCreateExp.setClassType($classType.cType);}
    GROUP_START (argumentList {$clsCreateExp.setArgumentList($argumentList.argLst);}) ?
    GROUP_END
    ;

arrayCreationExpression returns[ArrayCreationExpression arrCreateExp]
@init{
    $arrCreateExp = new ArrayCreationExpression();
}
@after{
    $arrCreateExp.validate();
}
    : type {$arrCreateExp.setType($type.type);}
    RECTANGLE_OPEN expression {$arrCreateExp.setExpression($expression.exp);}
    RECTANGLE_CLOSE (dimension {$arrCreateExp.increaseDimension();})*
    ;

newInstance returns[NewInstance newInst]
@init{
    $newInst = new NewInstance();
}
  :
  NEW
  (
    classInstanceCreationExpression {
        $newInst.setCreationExpression($classInstanceCreationExpression.clsCreateExp);
    }
    | arrayCreationExpression {
        $newInst.setCreationExpression($arrayCreationExpression.arrCreateExp);
    }
  )
  ;

dimension
    : RECTANGLE_OPEN RECTANGLE_CLOSE
    ;

